Parte 8 bis - Introducción a Protocolos

Contexto

Ahora que hemos visto planes, introduciremos un nuevo objeto llamado el protocolo. Un protocolo coordina una secuencia de planes, los lanza en trabajadores distantes y los corre en una sola pasada.

Es un objeto de alto nivel el cual contiene la lógica de una computación compleja distribuida por varios trabajadores. La característica más importante de un protocolo es la habilidad de ser enviado/ buscado / extraído de vuelta entre trabajadores, y finalmente lanzado a trabajadores identificados. Entonces un usuario puede diseñar un protocolo, subirlo a un trabajador en la nube y otros trabajadores podrán buscarlo, descargarlo y aplicar el programa que está contenido en los trabajadores que están conectados.

¡Veamos como podemos usarlo!

Autores:

Traductores:

1. Crear y lanzar

Los protocolos son creados al proveer un lista de parejas (trabajador, plan). trabajador puede ser un trabajador real o un id de trabajador o una cadena de caracteres que representan un trabajador ficticio. Este último caso puede ser usado en la creación para especificar que 2 planes deben ser apropiados (o no) por el mismo trabajador en el lanzamiento. plan puede ser un plan o un PointerPlan


In [ ]:
import torch as th
import syft as sy
hook = sy.TorchHook(th)

# IMPORTANTE: El trabajador local no debe ser un trabajador cliente
hook.local_worker.is_client_worker = False

Vamos a definir 3 planes y alimentarlos a un protocolo. Todos ellos realizan una operación de incremento.


In [ ]:
@sy.func2plan(args_shape=[(1,)])
def inc1(x):
    return x + 1

@sy.func2plan(args_shape=[(1,)])
def inc2(x):
    return x + 1

@sy.func2plan(args_shape=[(1,)])
def inc3(x):
    return x + 1

protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])

Ahora necesitamos conectar el protocolo a los trabajadores, lo cual es realizado llamando .deploy(*workers). Vamos a crear algunos trabajadores.


In [ ]:
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
charlie = sy.VirtualWorker(hook, id="charlie")

In [ ]:
workers = alice, bob, charlie

protocol.deploy(*workers)

Tú puedes ver que los planes han sido enviados a los trabajadores apropiados: se ha lanzado!

Esto se ha hecho en 2 fases: primero, mapeamos los trabajadores ficticios obtenidos en la creación (llamados por cadenas) a los trabajadores obtenidos, y segundo, enviamos los planes correspondientes a cada uno.

2. Correr un protocolo

Correr un protocolo significa ejecutar todos los planes secuencialmente. Para hacer esto, provees algunas entradas que son enviadas a ubicación del primer plan. El primer plan es ejecutado y su resultado es movido a la ubicación del segundo plan, y así. El resultado final es obtenido después de que se han ejecutado todos los planes, y está compuesto de punteros hasta la última ubicación de plan.


In [ ]:
x = th.tensor([1.0])
ptr = protocol.run(x)
ptr

In [ ]:
ptr.get()

La entrada 1.0 ha pasado por 3 planes y ha incrementado 3 veces, por eso ahora es igual a 4!

En realidad, tu puedes correr un protocolo remotamente en algunos punteros a los datos:


In [ ]:
james = sy.VirtualWorker(hook, id="james")

In [ ]:
protocol.send(james)

In [ ]:
x = th.tensor([1.0]).send(james)
ptr = protocol.run(x)
ptr

Como ves el resultado es un puntero a james


In [ ]:
ptr = ptr.get()
ptr

In [ ]:
ptr = ptr.get()
ptr

3. Buscar por un protocolo

En una configuración real tú podrías querer descargar un protocolo remoto, para lanzarlo en tus trabajadores y ejecutarlo con tus datos:

Vamos a iniciar un protocolo el cual no está lanzado, y ponerlo en un trabajador remoto


In [ ]:
protocol = sy.Protocol([("worker1", inc1), ("worker2", inc2), ("worker3", inc3)])
protocol.tag('my_protocol')
protocol.send(james)

In [ ]:
me = sy.hook.local_worker # consigue acceso a me como un trabajador local

Ahora lanzamos una búsqueda para encontrar el protocolo


In [ ]:
responses = me.request_search(['my_protocol'], location=james)
responses

Tú tienes acceso a un puntero al protocolo


In [ ]:
ptr_protocol = responses[0]

como un puntero cualquiera, tú puedes traerlo de vuelta:


In [ ]:
protocol_back = ptr_protocol.get()
protocol_back

y podemos hacer lo que hicimos en partes 1. & 2.


In [ ]:
protocol_back.deploy(alice, bob, charlie)

x = th.tensor([1.0])
ptr = protocol_back.run(x)
ptr.get()

Más ejemplos del mundo real vendrán con protocolos, pero enseguida puedes ver todas las posibilidades que se abren por este nuevo objeto!

Dale una Estrella a PySyft en Github

La forma más fácil de ayudar a nuestra comunidad es guardando con una estrella los Repos! Esto ayuda a crear consciencia de las geniales herramientas que estamos construyendo.

¡Usa nuestros tutoriales en Github!

Hicimos muy buenos tutoriales para conseguir un mejor entendimiento de lo que aprendizaje federado y aprendizaje que preserva la privacidad debe ser y cómo construimos los bloques para que esto pase.

¡Únete a nuestro Slack!

La mejor manera de mantenerte actualizado con los últimos avances es ¡unirte a la comunidad!

¡Únete a un proyecto de código!

La mejor manera de contribuir a nuestra comunidad es convertirte en un ¡contribuidor de código! Si quieres empezar un mini proyecto, puedes ir a la página PySyft GitHub Issues y buscar por issues marcados como Good First Issue.

Donar

Si no tienes tiempo para contribuir a nuestra base de código, pero quieres ofrecer tu ayuda, también puedes aportar a nuestro Open Collective. Todas las donaciones van a nuestro web hosting y otros gastos de nuestra comunidad como ¡hackathons y meetups!